//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include <stdlib.h>
#include "crt0.h"

#define AE_ALLOCATE_SLOTS   32  /* Allocate so many entries at a time, which */
/* must be power of 2 and >= 32 (for ANSI) */

static PATEXIT_DATA s_pExeExitStack = NULL;

int __cdecl __doatexit(EXIT_FUNCTION func, PATEXIT_DATA *ppFuncStack)
{
    PATEXIT_DATA pFuncStack = *ppFuncStack;
    int Index, RetValue;
    RetValue = 0;

    if ((int)func == 0) {  /* Called by _Exit(), so remove stack */
        if (pFuncStack != NULL) {
            free(pFuncStack);
            *ppFuncStack = NULL;
        }

        /* NOTENOTE - Leave the mutex locked so nobody, except me,
         * will be able to enter again!
         */
        return RetValue;
    }

    if ((int)func == -1) {  /* Called by _AtExit(), so call C++ dtors */
        if (pFuncStack != NULL) {
            for (Index = pFuncStack->Entries - 1; Index >= 0; Index--) {
                (*pFuncStack->Array[Index])();
            }
            free(pFuncStack);
            *ppFuncStack = NULL;
        }
        goto Out;
    }

    if (pFuncStack != NULL) {
        Index = pFuncStack->Entries;

        if ((Index & (AE_ALLOCATE_SLOTS - 1)) != 0)
            goto Succeed;
    }
    else {
        Index = 0;
    }

    pFuncStack = (PATEXIT_DATA)realloc(pFuncStack, sizeof(ATEXIT_DATA) +
                     (Index + AE_ALLOCATE_SLOTS - 1) * sizeof(EXIT_FUNCTION));
    if (pFuncStack == NULL) {
        RetValue = -1;
        goto Out;
    }

    *ppFuncStack = pFuncStack;

Succeed:
    pFuncStack->Array[Index] = func;
    pFuncStack->Entries = Index + 1;
Out:
    return RetValue;
}

int __cdecl __exeatexit(EXIT_FUNCTION func)
{
    return __doatexit(func, &s_pExeExitStack);
}
